/*****************************************************************************
 *
 * Microchip DeviceNet Stack 
 * (Network Access State Machine management source code)
 *
 *****************************************************************************
 * FileName:        NASM.c
 * Dependencies:    
 * Processor:       PIC18F with CAN
 * Compiler:       	C18 02.20.00 or higher
 * Linker:          MPLINK 03.40.00 or higher
 * Company:         Microchip Technology Incorporated
 *
 * Software License Agreement
 *
 * The software supplied herewith by Microchip Technology Incorporated
 * (the "Company") is intended and supplied to you, the Company's
 * customer, for use solely and exclusively with products manufactured
 * by the Company. 
 *
 * The software is owned by the Company and/or its supplier, and is 
 * protected under applicable copyright laws. All rights are reserved. 
 * Any use in violation of the foregoing restrictions may subject the 
 * user to criminal sanctions under applicable laws, as well as to 
 * civil liability for the breach of the terms and conditions of this 
 * license.
 *
 * THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES, 
 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED 
 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, 
 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR 
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 *
 *
 * This file contains the Network Access State Machine (NASM) managing 
 * functions. All the functions work closely with the Duplicate ID messaging
 * provided by the connection object. Refer to Chapter 6 of Volume 1 of the 
 * DeviceNet Specification for more information.
 * 
 *
 *
 * Author               Date        Comment
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * Ross Fosler			06/06/03	...	
 * 
 *****************************************************************************/


#include	"dnetdef.h"				// Global definitions file
#include 	"typedefs.h"

#include	"nasm.h"				// Internal definitions

#include	"services.h"			// Service codes
#include	"errors.h"				// Error codes
#include	"class.h"				// Class codes
				
#include 	"conn.h"				// Connection object 
#include	"dnet.h"				// DeviceNet Object
#include	"ident.h" 				// Identity Object


/*********************************************************************
 * Common control registers
 ********************************************************************/

 BYTE _aNASMInternalCtl;
 USINT _aNASMStates;
 UINT _aNASMWaitTimer;
 USINT _aNASMBaud;



/*********************************************************************
 * Function:        void _NASMAutoBaudStateManager(void)
 *
 * PreCondition:  	none  
 *
 * Input:       	none			
 *                  
 * Output:     		none
 * 	
 * Side Effects:   	none 
 *
 * Overview:        This function attempts to determine the baud rate
 *					by using the Duplicate ID messaging.  
 *
 * Note:            none
 ********************************************************************/
 #if (0)
void _NASMAutoBaudStateManager(void)
{
	// If baud rate switch value is not valid 
	if (uDNet.BaudSwValue > 2)
	{
		// If no bus off error
		if (!_ConnBusOffErr())
		{
			// If write not yet finished
			if (!_ConnWriteFin(7))
			{
				// If the write buffer is available	and not previously locked
				if (_ConnWriteRdy(7) && !_aNASMInternalCtl.bits.b0) 
				{
					// Prevent re-entry
					_aNASMInternalCtl.bits.b0 = 1;

					// Send duplicate ID		 
					_NASMWriteDuplicateID(0x00);
					_ConnWrite(7);
				}
			}

			// Write to bus successful, baud rate good
			else
			{
				// Release the internal write lock
				_aNASMInternalCtl.bits.b0 = 0;

				// Change to the waiting state
				_aNASMStates = _NASM_WAITING_DID;

				// Notify app of the baud rate for saving	TODO
			}
		}

		// bus off error
		else
		{
			if (_aNASMBaud < 2)
			{
				_aNASMBaud++;

				// Go off bus					TODO
				// reset the bit rate
				// Go on bus
			}
			else
			{
				// Transfer to FAULT state
				_aNASMStates = _NASM_COMM_FAULT;
			}
		}
	}

	// Valid baud rate 
	else
	{
		// Go back to the sending state
		_aNASMStates = _NASM_SENDING_DID;
	}
}
#endif



/*********************************************************************
 * Function:        void _NASMSendingDupIDStateManagder(void)
 *
 * PreCondition:  	none  
 *
 * Input:       	none			
 *                  
 * Output:     		none
 * 	
 * Side Effects:   	none 
 *
 * Overview:        This function manages Duplicate ID messaging while
 *					in the Sending Duplicate ID state.  
 *
 * Note:            none
 ********************************************************************/
void _NASMSendingDupIDStateManagder(void)
{
	// If there is no bus off error
	if (!_ConnBusOffErr())
	{
		// If there is no data in the read buffer
		if (!_ConnReadRdy(7))
		{
			// If no data from this connection has been placed on the bus
			if (!_ConnWriteFin(7))
			{
				// If the write buffer is available and not previously locked
				if (_ConnWriteRdy(7) && !_aNASMInternalCtl.bits.b0) // and internal lock
				{
					// Prevent re-entry
					_aNASMInternalCtl.bits.b0 = 1;
				
					// Send duplicate ID					
					_NASMWriteDuplicateID(0x00);
					_ConnWrite(7);
				}
			}
			
			// Data has been placed on the bus
			else
			{
				// Release the internal write lock
				_aNASMInternalCtl.bits.b0 = 0;
				
				// Change to the waiting state
				_aNASMStates = _NASM_WAITING_DID;
				
				// Start timer at 1000ms
				_aNASMWaitTimer.word = 1000;
			}
		}
		
		// Connection received a Duplicate ID
		else
		{
			// If rec DID then transfer to FAULT
			_aNASMStates = _NASM_COMM_FAULT;
			_ConnRead(7);
		}
	}
	
	// Bus error, goto fault state
	else
	{
		_aNASMStates = _NASM_COMM_FAULT;
	}
}




/*********************************************************************
 * Function:        void _NASMWaitingForDupIDStateManager(void)
 *
 * PreCondition:  	none  
 *
 * Input:       	none			
 *                  
 * Output:     		none
 * 	
 * Side Effects:   	none 
 *
 * Overview:        This function manages Duplicate ID messaging while
 *					in the Waiting for Duplicate ID state.  
 *
 * Note:            none
 ********************************************************************/
void _NASMWaitingForDupIDStateManager(void)
{
	// If there is no bus off error
	if (!_ConnBusOffErr())
	{
		// If there is no data in the read buffer
		if (!_ConnReadRdy(7))
		{
			// If timer expired
			if (_aNASMInternalCtl.bits.b2)
			{
				// Reset the timer flag
				_aNASMInternalCtl.bits.b2 = 0;
			
				// If this is the second wait sequence then 
				if (_aNASMInternalCtl.bits.b1)
				{
					// Go on-line
					_aNASMStates = _NASM_ON_LINE;
					_aNASMInternalCtl.bits.b1 = 0;
				}
				
				// This is the first wait time out
				else
				{
					// Go back to the sending state
					_aNASMStates = _NASM_SENDING_DID;
					_aNASMInternalCtl.bits.b1 = 1;
				}
			}
		}
		
		// Connection received a Duplicate ID
		else
		{
			// If rec DID then transfer to FAULT
			_aNASMStates = _NASM_COMM_FAULT;
			_ConnRead(7);
		}
	}
	
	// Bus error, goto fault state
	else
	{
		_aNASMStates = _NASM_COMM_FAULT;
	}
}




/*********************************************************************
 * Function:        void _NASMOnLineStateManager(void)
 *
 * PreCondition:  	none  
 *
 * Input:       	none			
 *                  
 * Output:     		none
 * 	
 * Side Effects:   	none 
 *
 * Overview:        This function manages Duplicate ID messaging while
 *					in the on-line state.  
 *
 * Note:            none
 ********************************************************************/
void _NASMOnLineStateManager(void)
{
	// If there is no bus off error
	if (!_ConnBusOffErr())
	{
		// If duplicate ID has been received
		if (_ConnReadRdy(7))
		{
			// If the duplicate ID is a response
			if (((BYTE *)uConn7.rx.pMsg)->bits.b7)
			{
				_aNASMStates = _NASM_COMM_FAULT;
			}
			
			// the duplicate ID is a request
			else
			{
				// If the write buffer is available
				if (_ConnWriteRdy(7))
				{
					// Send DID				
					_NASMWriteDuplicateID(0x80);
					_ConnWrite(7);
				}
			}
			
			// Release the buffer to accept more data
			_ConnRead(7);			
		}
	}
	
	// Bus off error
	else
	{
		// Hold in reset
		if (mDNetGetBOI() == 0)
		{
			// If rec DID then transfer to FAULT
			_aNASMStates = _NASM_COMM_FAULT;
		}
		else

		// Automatic reset
		if (mDNetGetBOI() == 1)
		{
			// Go back to the sending state
			_aNASMStates = _NASM_SENDING_DID;		// May need to add code to recover last running mode
		}
	}
}






/*********************************************************************
 * Function:        void _NASMWaitTimeManager(void)
 *
 * PreCondition:  	none  
 *
 * Input:       	none			
 *                  
 * Output:     		none
 * 	
 * Side Effects:   	none 
 *
 * Overview:        This funcion adjusts the Network Access State 
 *					Machine timer.  
 *
 * Note:            none
 ********************************************************************/
void _NASMWaitTimeManager(void)
{
	// Update the time for network wait to be established
	if (_aNASMWaitTimer.word)
	{
		// Adjust the time
		_aNASMWaitTimer.word -= TICK_RESOLUTION;
	}
	else
	{		
		// Set flag indicating the time has expired
		_aNASMInternalCtl.bits.b2 = 1;
	}		
}




/*********************************************************************
 * Function:        void _NASMWriteDuplicateID(void)
 *
 * PreCondition:    
 *
 * Input:       			
 *                  
 * Output:     
 * 	
 * Side Effects:    
 *
 * Overview:        Write the Vendor ID and Serial number to the
 *					transmit buffer.  
 *
 * Note:            None
 ********************************************************************/
void _NASMWriteDuplicateID( unsigned char portNoAndReq)
{
	*((unsigned char *)uConn7.tx.pMsg) = portNoAndReq;
	*((unsigned char *)(uConn7.tx.pMsg + 1)) = mIdentityGetVendorIDL();
	*((unsigned char *)(uConn7.tx.pMsg + 2)) = mIdentityGetVendorIDH();
	*((unsigned char *)(uConn7.tx.pMsg + 3)) = mIdentityGetSerialL();
	*((unsigned char *)(uConn7.tx.pMsg + 4)) = mIdentityGetSerialH();
	*((unsigned char *)(uConn7.tx.pMsg + 5)) = mIdentityGetSerialUL();
	*((unsigned char *)(uConn7.tx.pMsg + 6)) = mIdentityGetSerialUH();

	uConn7.tx.len = 7;
}





/*********************************************************************
 * Function:        void _NASMInit(void)
 *
 * PreCondition:    
 *
 * Input:       			
 *                  
 * Output:     
 * 	
 * Side Effects:    
 *
 * Overview:        Initialize the Network Access State Machine.  
 *
 * Note:            None
 ********************************************************************/
void _NASMInit(void)
{
	// Reset network access states
	_aNASMStates = 1;
	
	// Reset network access state control bits
	_aNASMInternalCtl.byte = 0;

	// Reset the autobaud 
	//_aNASMBaud = 0;

}
